#准备工作和添加布景
import math
import pygame
from pygame.locals import *
import random

running = 1

pygame.init()   #初始化
width, height = 640, 480
screen = pygame.display.set_mode((width, height))  #窗口大小
key_tag = [False,False,False,False]    #标记变量 W|A|S|D
dudepos = [100,100]
arrows = []
badguys = []
timer = random.randint(30,60)
n = 0
mun = 0
add = 0
total_time = 0.5 #分钟
acc = [0,0]      #[0,0] [射中,射出]

dude = pygame.image.load('D:/pythonX/resources/images/dude.png')     #导入图片
grass = pygame.image.load('D:/pythonX/resources/images/grass.png')
castle = pygame.image.load('D:/pythonX/resources/images/castle.png')
bullet = pygame.image.load('D:/pythonX/resources/images/bullet.png')
badguy = pygame.image.load('D:/pythonX/resources/images/badguy.png')
badguy2 = pygame.image.load('D:/pythonX/resources/images/badguy2.png')
badguy3 = pygame.image.load('D:/pythonX/resources/images/badguy3.png')
badguy4 = pygame.image.load('D:/pythonX/resources/images/badguy4.png')
all_badguys = [badguy,badguy2,badguy3,badguy4]
redbar = pygame.image.load('D:/pythonX/resources/images/healthbar.png')
greenbar = pygame.image.load('D:/pythonX/resources/images/health.png')
youwin = pygame.image.load('D:/pythonX/resources/images/youwin.png')
gameover = pygame.image.load('D:/pythonX/resources/images/gameover.png')
#音乐
hit = pygame.mixer.Sound("D:/pythonX/resources/audio/explode.wav")
enemy = pygame.mixer.Sound("D:/pythonX/resources/audio/enemy.wav")
shoot = pygame.mixer.Sound("D:/pythonX/resources/audio/shoot.wav")

hit.set_volume(0.05)    #音量 0.0-1.0
enemy.set_volume(0.05)
shoot.set_volume(0.05)

pygame.mixer.music.load("D:/pythonX/resources/audio/moonlight.wav")
channel = pygame.mixer.find_channel(True)
pygame.mixer.music.play(-1, 0.0)   #(播放几次,音乐从哪播放)   -1表示无限循环播放
pygame.mixer.music.set_volume(0.25) #音量

while running:
    screen.fill(0)
    # 草坪
    if width % grass.get_width() != 0:
        ws_grass = int(width // grass.get_width()) + 1
    else:
        ws_grass = int(width // grass.get_width())
    if height % grass.get_height() != 0:
        hs_grass = int(height // grass.get_height()) + 1
    else:
        hs_grass = int(height // grass.get_height())

    for x in range(ws_grass):
        for y in range(hs_grass):
            screen.blit(grass, (x * grass.get_width(), y * grass.get_height()))

    # for x in range(int(width / grass.get_width()) + 1):
    #     for y in range(int(height / grass.get_height()) + 1):
    #         screen.blit(grass, (x * 100, y * 100))

    # 兔子窝
    for i in range(4):
        screen.blit(castle, (0, (i * 105 + 30)))
    # 兔子
    # screen.blit(dude, dudepos)  # 参数：图片对象，坐标位置
    x2 = pygame.mouse.get_pos()[0]
    y2 = pygame.mouse.get_pos()[1]
    # 计算兔子中心的位置
    x1 = dudepos[0] + dude.get_width() / 2
    y1 = dudepos[1] + dude.get_height() / 2
    # 计算旋转弧度 -- tanθ = (y2-y1)/(x2-x1)  θ=arctan(y2-y1)/(x2-x1)
    angle_1 = math.atan2(y2 - y1, x2 - x1)
    # 角度
    angle_2 = -angle_1 * 360 / (2 * math.pi)
    # 将弧度转换为角度，并且旋转兔子图片，得到新的兔子图片对象
    duderot = pygame.transform.rotate(dude, angle_2)

    # 计算旋转后兔子图片的位置
    dudepos1 = (x1 - duderot.get_width() / 2, y1 - duderot.get_height() / 2)

    # 将旋转后的兔子图片放置到计算后的位置
    screen.blit(duderot, dudepos1)
    for event in pygame.event.get():
        #退出窗口事件
        if event.type == QUIT:
            pygame.quit()
            exit(0)
        #按键事件 按下|抬起
        elif event.type == KEYDOWN:
            if event.key == K_w:
                key_tag[0] = True
            elif event.key == K_a:
                key_tag[1] = True
            elif event.key == K_s:
                key_tag[2] = True
            elif event.key == K_d:
                key_tag[3] = True
        elif event.type == KEYUP:
            if event.key == K_w:
                key_tag[0] = False
            elif event.key == K_a:
                key_tag[1] = False
            elif event.key == K_s:
                key_tag[2] = False
            elif event.key == K_d:
                key_tag[3] = False

        elif event.type == MOUSEBUTTONDOWN:
            shoot.play()
            acc[1] += 1 #射出箭
            point_x = dudepos1[0] + dude.get_width() / 2
            point_y = dudepos1[1] + dude.get_height() / 2

            mouse_x = pygame.mouse.get_pos()[0]
            mouse_y = pygame.mouse.get_pos()[1]

            arrow_angle = math.atan2(mouse_y - point_y, mouse_x - point_x)

            arrows.append([arrow_angle, point_x, point_y])

    #每次移动距离
    step = 2
    if key_tag[0]:
        dudepos[1] -= step
    if key_tag[1]:
        dudepos[0] -= step
    if key_tag[2]:
        dudepos[1] += step
    if key_tag[3]:
        dudepos[0] += step



    #射箭

    vel_arrow = 8      #箭的步距
    removed_arrows = []
    for arrow in arrows:

        arrow[1] += vel_arrow * math.cos(arrow[0])
        arrow[2] += vel_arrow * math.sin(arrow[0])
        if (arrow[1] > width or arrow[1] < -bullet.get_width() or
                arrow[2] > height or arrow[2] < -bullet.get_height()):
            removed_arrows.append(arrow)

    #显示箭
    for arrow in arrows:
        bulletrot = pygame.transform.rotate(bullet, -360 * arrow[0] / (2 * math.pi))
        screen.blit(bulletrot, [arrow[1], arrow[2]])

    #生成并更新显示badguy
    if timer == 0:
        guy_x = width
        guy_y1 = 30
        guy_y2 = 345+castle.get_height()
        guy_y = random.randint(guy_y1,guy_y2)
        badguys.append([guy_x,guy_y])
        timer = random.randint(30,60)

    vel_guy = 2
    removed_badguys = []
    for guy in badguys:
        guy[0] -= vel_guy
        if guy[0] < castle.get_width():
            hit.play()#掉血音效
            # 判断老鼠超过兔子窝
            removed_badguys.append(guy)
            mun += 1
        else:
            for arrow in arrows:
                # 获取图片对象矩形框
                guyrect = badguy.get_rect()
                arrowrect = bullet.get_rect()
                # 调整矩形框左上角位置为图片对象当前位置
                guyrect.left = guy[0]
                guyrect.top = guy[1]
                arrowrect.left = arrow[1]
                arrowrect.top = arrow[2]
                # 检测是否有重合，并根据结果删除箭和老鼠
                # （把前面删除箭和显示箭的代码调整到判断重合之后）
                if guyrect.colliderect(arrowrect):
                    enemy.play() #射中音效
                    acc[0] += 1
                    removed_badguys.append(guy)
                    removed_arrows.append(arrow)
                    add += 1
                    if m_greenbar >= n_greenbar:
                          add = 0
                          mun = 0
    #删除箭
    for arrow in removed_arrows:
        if arrow in arrows:
            arrows.remove(arrow)
    for guy in removed_badguys:
        badguys.remove(guy)
    n += 1
    for guy in badguys:
        screen.blit(all_badguys[n%4],guy)
    timer -= 1


    # 生命条显示
    vel_mun = 10
    n_greenbar = redbar.get_width() // greenbar.get_width()
    m_greenbar = n_greenbar - (mun - add) * vel_mun
    barpos = [200, 0]  # 设定生命条的显示位置
    screen.blit(redbar, barpos)  # 红条显示
    for m in range(m_greenbar - 6):
        screen.blit(greenbar, (3 + barpos[0] + m * greenbar.get_width(), barpos[1] + 3))

    #倒计时

    taken_time = pygame.time.get_ticks()    #得到以毫秒为间隔的时间
    left_time = total_time*60000 - taken_time #剩余时间（毫秒）
    font_time = pygame.font.SysFont('arial', 24)  # 设置 字体 字号

    time_min = str(int(left_time//60000))   #剩余分
    time_sec = str(int(left_time%60000//1000))   #剩余秒

    text_time = time_min.zfill(2)+':'+time_sec.zfill(2) #str.zfill(width)  width -- 指定字符串的长度。原字符串右对齐，前面填充0
    time = font_time.render(text_time,False,(255,102,0)) #设置 内容 圆滑度 RGB

    screen.blit(time,(500,10))
    #round( x[, n]) ，对x保留四舍五入到n位小数
    # 计算命中率
    if acc[1] != 0:
        accuracy = round((acc[0] * 1.0 / acc[1] * 100),2)
    else:
        accuracy = 0
    # 判断输赢
    font_a = pygame.font.Font(None, 24)
    text_result = 'accuracy:' + str(accuracy) + '%'

    if m_greenbar <= 0:
        running = 0
        screen.blit(gameover, (0, 0))
        result_a = font_a.render(text_result, True, (255, 0, 0))#设置要显示命中率
        screen.blit(result_a, (200, 150))#显示命中率
        pygame.mixer.music.stop()
    else:
        if taken_time >= total_time * 60000:
            running = 0
            result_text = font_a.render(text_result, True, (0, 255, 0))
            screen.blit(youwin, (0, 0))
            screen.blit(result_text, (200, 150))
            pygame.mixer.music.stop()


    pygame.display.flip()       #窗口更新


while 1:
    for event in pygame.event.get():
        #4.1.1 监测并处理退出事件
        if event.type == QUIT:
            pygame.quit()
            exit(0)
